﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows.Forms;
using DDay.iCal;
using DataTransferObject;
using DataTransferObject.MapUnMapTime;
using DataService.LocalFile;
using DDay.iCal.Components;
using System.Data;
using DataTransferObject.DiaryAndTrackingTask.SupportClassForDiary;
using DataTransferObject.DiaryAndTrackingTask;
using DataTransferObject.DiaryAndTrackingTask.SupportClassForUpdateTask;
using System.Drawing;
using DataService;


namespace Engine
{
    /*
     * Là Manager cho tất cả các template xử lý giải thuật & linh kiện giao tiếp của JSKE
     */
    /// <summary>
    /// 
    /// </summary>
    public class JskeEngine
    {
        #region Attributes

        private static JskeDataService dataService = new JskeDataService();

        private TaskList taskList = new TaskList();

        private SystemConfiguration systemConfiguration = SystemConfiguration.getInstance();
        private String inputCalendarPath;
        private String outputCalendarPath;
        private String pathForSystemConfigFile;

        private FreeTimeList freeTimeListForSchedule;

        private DiaryDS diary = new DiaryDS();
        private ListEvent scheduleList = new ListEvent();
        private TrackingTaskDS trackingTask = new TrackingTaskDS();
        
        private static JskeEngine currentJskeEngine = null;

        #endregion

        #region Properties

        public FreeTimeList FreeTimeListForSchedule
        {
            get { return this.freeTimeListForSchedule; }
            set { this.freeTimeListForSchedule = value; }
        }
        
        public TaskList TaskList
        {
            get { return this.taskList; }
            set { this.taskList = value; }
        }

        public SystemConfiguration SystemConfiguration
        {
            get { return this.systemConfiguration; }
            set { this.systemConfiguration = value; }
        }

        public String InputCalendarPath
        {
            get { return this.inputCalendarPath; }
            set { this.inputCalendarPath = value; }
        }

        public String OutputCalendarPath
        {
            get { return this.outputCalendarPath; }
            set { this.outputCalendarPath = value; }
        }

        public String PathForSystemConfigFile
        {
            get { return this.pathForSystemConfigFile; }
            set { this.pathForSystemConfigFile = value; }
        }

        //public String PathForTaskListFile
        //{
        //    get { return this.pathForTaskListFile; }
        //    set { this.pathForTaskListFile = value; }
        //}

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="JskeEngine"/> class.
        /// </summary>
        private JskeEngine()
        {
            // chờ PresenterMainForm nạp xong dữ liệu rồi hãy dùng
            LoadTaskListFromFileToEngine(); 
           
        }
        private JskeEngine(int dataServiceMode)
        {
            // chờ PresenterMainForm nạp xong dữ liệu rồi hãy dùng
            LoadTaskListFromFileToEngine();
            dataService = new JskeDataService(dataServiceMode);
        }

        #endregion

        #region Essential Methods
        // single tone pattern
        /// <summary>
        /// Gets the instance.
        /// </summary>
        /// <returns></returns>
        public static JskeEngine getInstance(int dataServiceMode)
        {
            if (currentJskeEngine == null)
            {
                currentJskeEngine = new JskeEngine(dataServiceMode);
                return currentJskeEngine;
            }
            else
            {
                return currentJskeEngine;
            }
        }

        /*
         * Methods sau đây là một minh họa cho qui trình TaskFlow được mô tả trong groove
         * Đây là quả tim của PresenterMainForm, chịu trách nhiệm gọi các chức năng sau
         * 1. Kiểm tra ràng buộc task
         * 2. Tính toán, sắp xếp mức độ ưu tiên task
         * 3. Xếp lịch
         */

        #region Task Area
        public Task getTaskByID(int taskID)
        {
            return taskList.GetTaskByID(taskID);
        }

        /// <summary>
        /// Loads the task list from file to engine.
        /// </summary>
        /// <returns></returns>
        public void LoadTaskListFromFileToEngine()
        {
            createSampleDiary();
            createSampleTaskTracking();
            try
            {
                taskList = dataService.dbWorker.readTaskList();
                
            }
            catch (Exception ex)
            {
                Console.WriteLine("Khong doc duoc TaskList: " + ex.Message);
                //throw;
            }
        }

        /// <summary>
        /// Persists the task list.
        /// </summary>
        /// <param name="taskList">The task list.</param>
        /// <returns></returns>
        public void persistTaskList(TaskList taskList)
        {
            dataService.dbWorker.writeTaskList(taskList);
            
            //RWTaskList.WriteToTaskListFile(taskList, pathForTaskListFile);
        }

        public List<Task> getTaskList()
        {
            if (this.taskList != null)
            {
                return taskList.GetTaskList;
            }
            else
            {
                return new List<Task>();
            }
            //try
            //{
            //    return dataService.dbWorker.readTaskList().GetTaskList;
            //    //TaskList result = new TaskList();
            //    //RWTaskList.readTaskList(ref result);
            //    //return result.GetTaskList;
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine("Loi khi doc TaskList: " + ex.Message);
            //    return new List<Task>();
            //    //throw;
            //}
        }

        // Dùng cho MainForm gọi để chuyển 1 task ở mainForm vào tasklist, lưu xuống file, chờ xử lý
        /// <summary>
        /// Adds the task to list.
        /// </summary>
        /// <param name="task">The task.</param>
        /// <returns></returns>
        public Task AddTaskToTaskList(Task task)
        {
            
            taskList.AddTaskToList(task);
            dataService.dbWorker.writeTaskList(taskList);
            //RWTaskList.writeTaskList(taskList);
            //RWTaskList.WriteToTaskListFile(taskList, pathForTaskListFile);
            return task;
        }

        public void updateTaskList(Task updatedTask)
        {
            // chức năng update xuống file XML cần được tối ưu, để hỉ cần update với những Task bị edit
            // vì nếu số task lớn thì cost để write xuống file XML là khá lớn
            for (int i = 0; i < taskList.GetTaskList.Count; i++)
            {
                if (updatedTask.TaskID == taskList.GetTaskList[i].TaskID)
                {
                    taskList.GetTaskList[i] = updatedTask;
                    break;
                }
            }
            dataService.dbWorker.writeTaskList(taskList);
            //RWTaskList.WriteToTaskListFile(taskList, pathForTaskListFile);
        }

        public Boolean removeTaskAt(int positionInDataGridView)
        {
            Boolean result = false;
            int taskRemovedID = taskList.GetTaskList[positionInDataGridView].TaskID;
            int taskListLenght = taskList.GetTaskList.Count;
            int predecessorIDsLength = 0;
            Task tmp;
            for (int i = 0; i < taskListLenght; i++)
            {
                tmp = taskList.GetTaskList[i];
                predecessorIDsLength = tmp.PredecessorIDs.Count;
                for (int j = 0; j < predecessorIDsLength; j++)
                {
                    if (taskRemovedID == tmp.PredecessorIDs[j])
                    {
                        //remove the predecessor index
                        tmp.PredecessorIDs.RemoveAt(j);
                        result = true;
                        break;
                    }
                }
            }
            taskList.GetTaskList.RemoveAt(positionInDataGridView);
            dataService.dbWorker.writeTaskList(taskList);
            //RWTaskList.WriteToTaskListFile(taskList, pathForTaskListFile);
            result = true;
            return result;
        }

        public void deleteListTask(List<Task> delTaskList)
        {
            for (int i = 0; i < delTaskList.Count; i++)
            {
                deleteTask(delTaskList[i]);
            }
        }

        public Boolean deleteTask(Task delTask)
        {
            Boolean result = false;
            int taskRemovedID = delTask.TaskID;
            int taskListLenght = taskList.GetTaskList.Count;
            int predecessorIDsLength = 0;
            Task tmp;
            for (int i = 0; i < taskListLenght; i++)
            {
                tmp = taskList.GetTaskList[i];
                predecessorIDsLength = tmp.PredecessorIDs.Count;
                for (int j = 0; j < predecessorIDsLength; j++)
                {
                    if (taskRemovedID == tmp.PredecessorIDs[j])
                    {
                        //remove the predecessor index
                        tmp.PredecessorIDs.RemoveAt(j);
                        result = true;
                        break;
                    }
                }
            }
            if (taskList.GetTaskList.Count == 1)
            {
                taskList.GetTaskList.Clear();
            }
            else
            {
                for (int x = 0; x < taskList.GetTaskList.Count; x++)
                {
                    if (taskList.GetTaskList[x].TaskCode == delTask.TaskCode)
                    {
                        taskList.GetTaskList.RemoveAt(x);
                        break;
                    }
                }
            }
            dataService.dbWorker.writeTaskList(taskList);
            //RWTaskList.WriteToTaskListFile(taskList, pathForTaskListFile);
            result = true;
            return result;
        }

        public void DeleteTaskFromEngine(Task task)
        {
            throw new NotImplementedException();
        }
        #endregion

        #region SystemConfiguration Area
        /// <summary>
        /// Loads the system config from file to engine.
        /// </summary>
        /// <returns></returns>
        public void LoadSystemConfigFromFileToEngine()
        {
            systemConfiguration = dataService.dbWorker.ReadFromConfigFile();
            //RWOptionConfiguration.ReadFromConfigFile(ref systemConfiguration, pathForSystemConfigFile);
        }

        /// <summary>
        /// Persists the system config.
        /// </summary>
        /// <param name="saveObj">The save obj.</param>
        /// <returns></returns>
        public bool persistSystemConfig(SystemConfiguration saveObj)
        {
            return dataService.dbWorker.WriteToConfigFile(systemConfiguration);
        }

        //public void loadSystemConfigData()
        //{
        //    // tải lên thành phần system config
        //    systemConfiguration = SystemConfiguration.getInstance();
        //    RWOptionConfiguration.ReadFromConfigFile(ref systemConfiguration, pathForSystemConfigFile);
        //}

        #endregion

        private void updateProgressBar(ProgressBar progressBar1, int val)
        {
            progressBar1.Refresh();
            progressBar1.Value = val;
            int percent = (int)(((double)progressBar1.Value / (double)progressBar1.Maximum) * 100);
            progressBar1.CreateGraphics().DrawString(percent.ToString() + "%", new Font("Arial", (float)8.25, FontStyle.Bold), Brushes.Blue, new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));

        }

        /// <summary>
        /// Schedules the calendar.
        /// </summary>
        /// <returns></returns>
        public List<Event> ScheduleCalendar(ProgressBar progressBar1)
        {
           
            iCalendar iCal = new iCalendar();
            MappedFreeTimeList mappedFreeTimeList = new MappedFreeTimeList();

            // lấy instance của system config. Là instance duy nhất trong hệ thống
            systemConfiguration = SystemConfiguration.getInstance();

            LoadSystemConfigFromFileToEngine();

            updateProgressBar(progressBar1, 32);
            
            /* 
             * 
             * PHẦN QUAN TRỌNG NHẤT
             * 
             */
            if (systemConfiguration.TabWorkingHoursData.ListOfWorkingHourItems.Count == 0 || taskList.GetTaskList.Count == 0)
            {
                return null;
            }
            MappingService.mapFreeTimeBlock(freeTimeListForSchedule, ref mappedFreeTimeList);
            JskeAlgorithm algorithm = new PragmaticAlgorithm(taskList, iCal, mappedFreeTimeList, systemConfiguration, dataService);
            algorithm.setProgressBar(progressBar1);

            updateProgressBar(progressBar1, 44);

            List<Event> events = algorithm.run();
             /* 
             * 
             * ĐÃ GỌI XONG GIẢI THUẬT
             * 
             * 

            ConstraintViolation consViolation = algorithm.ConstraintViolate;
            ScheduleReport schedulReport = algorithm.ScheduReport;
            PrioritizeReport priorityReport = algorithm.PriorityReport;

            /*
             * đã schedule xong,bây giờ ghi kết quả ra file
             */

            //ICSIOProcessing.createICSOutputFile(iCal, events, outputCalendarPath);
            
            return events;
        }        

        public void NormalizeTaskWorkingHourIDAt(int deletedWH)
        {
            Boolean changed = false;
            //duyet danh sach tasklist
            for (int i = 0; i < taskList.GetTaskList.Count; i++)
            {
                // neu day la task thuoc working hour bi xoa thi gan ve 0
                if (taskList.GetTaskList[i].WorkingHourID == deletedWH)
                {
                    taskList.GetTaskList[i].WorkingHourID = 0;
                    changed = true;
                }
                    //neu nhu day la nhung task thuoc working hour phia sau workinghour bi xoa thi dich ve truoc 1 don vi
                else if (taskList.GetTaskList[i].WorkingHourID > deletedWH)
                {
                    taskList.GetTaskList[i].WorkingHourID = taskList.GetTaskList[i].WorkingHourID - 1;
                    changed = true;
                }
            }
            if (changed)
            {
                dataService.dbWorker.writeTaskList(taskList);
                //RWTaskList.WriteToTaskListFile(taskList, pathForTaskListFile);
            }
        }

        //public JCalendarEvent GetJCalendarEvent(String path)
        //{
        //    JCalendarEvent jCalEvent = new JCalendarEvent();
        //    RWJCalendarEvent.ReadFromFile(ref jCalEvent, path);
        //    return jCalEvent;
        //}
        //public Boolean SaveJCalendarEvent(JCalendarEvent jCalEvent, String path)
        //{
        //    return RWJCalendarEvent.WriteToFile(jCalEvent, path);
        //}

        #region Diary and Tracking Area

        #region create Test entities
        private void createSampleDiary()
        {
             DiaryDS diary = new DiaryDS();
             diary.TheEventType.TypeName.Add("Sleep");
             diary.TheEventType.TypeName.Add("JSKE");
             diary.TheEventType.TypeName.Add("You-Light");
             diary.TheEventType.TypeName.Add("Enghlish");
             diary.TheEventType.TypeName.Add("Errands");
             diary.TheEventType.TypeName.Add("Email");
             diary.TheEventType.TypeName.Add("Wait");
             diary.TheEventType.TypeName.Add("Break");
             diary.TheEventType.TypeName.Add("Eat");
             diary.TheEventType.TypeName.Add("Bath");   
             diary.TheEventType.TypeName.Add("Meeting");
             diary.TheEventType.TypeName.Add("Telephone");
             diary.TheEventType.TypeName.Add("Internet");
             diary.TheEventType.TypeName.Add("Move");
             diary.TheEventType.TypeName.Add("Paper & Document");
             diary.TheEventType.TypeName.Add("Prepare");
             diary.TheEventType.TypeName.Add("Planning");
             diary.TheEventType.TypeName.Add("Leave");
             diary.TheEventType.TypeName.Add("Gossip");
             diary.TheEventType.TypeName.Add("Toilet");
             diary.TheEventType.TypeName.Add("Clean teeth");
             diary.TheEventType.TypeName.Add("Others");
            List<JskeEvent> result = new List<JskeEvent>();
            Random random = new Random();
            int sumtime;
            for (int i = 0; i < 365; i++)
            {
                sumtime = 0;
                for (int j = 0; j < 24; j++)
                {
                    if(sumtime >= 1440)
                    {
                        break;
                    }
                    JskeEvent ne = new JskeEvent();
                    ne.EventDuration = random.Next(0, 500);
                    sumtime += ne.EventDuration;
                    ne.EventID = DateTime.Now.GetHashCode()+ 1 +  i+ j + 1;
                    ne.EventName = "event: " + Convert.ToString(i) + "-"+ Convert.ToString(j);
                    ne.EventPriority = (EventPriority) random.Next(0, 5%(j+1));
                    ne.EventSatisfy = (EventSatsified)random.Next(0, 3%(j+1));
                    ne.EventStart = DateTime.Now.Date.AddDays(-365 + i);
                    if(result.Count > 0)
                    {
                        ne.EventStart = result.Last().EventStart.AddMinutes(result.Last().EventDuration);
                    }
                    else
                    {
                            ne.EventStart = DateTime.Now.Date.AddDays(-365);
                    }
                    ne.EventType = diary.TheEventType.TypeName[random.Next(0, diary.TheEventType.TypeName.Count%(j+22))];
                    ne.Money = random.Next(0, 150);
                    //ne.Notes = Convert.ToString(ne.EventID);

                    result.Add(ne);
                }
            }

           
            diary.ListEventInDiary = result;
            dataService.dbWorker.WriteDiaryDS(diary);
        }
        /// <summary>
        /// một task sẽ chỉ tồn tại khoảng 1 tháng là kết thúc. burndown sẽ chứa tối đa 20 task ma, active chỉ 8 task
        /// </summary>
        private void createSampleTaskTracking()
        {
            TrackingTaskDS tracking = new TrackingTaskDS();
            List<TaskWorked> result = new List<TaskWorked>();
            List<Task> listGhostTask = new List<Task>();
            Random r = new Random();
            DateTime startTS = DateTime.Now.Date.AddDays(-365);
            for (int i = 0; i < 14; i++)
            {
                int jump = 1;
                
                for (int j = 0; j < 30; j++)
                {
                    if (listGhostTask.Count < r.Next(3, 6))
                    {
                        listGhostTask.AddRange(createGhostTask(listGhostTask, r.Next(6, 12), i, j));
                    }

                    if (jump >= 30)
                    {
                        break;
                    }
                    DateTime curTS = startTS.AddDays((Double)((i)*30 + jump));
                    // tao list taskworked
                    result.AddRange(createListGhostTW(listGhostTask, curTS));
                    for (int k = 0; k < listGhostTask.Count; k++)
                    {
                        if (listGhostTask[k].RemainTime == 0)
                        {
                            listGhostTask.Remove(listGhostTask[k]);
                            k--;
                        }
                    }
                    jump += r.Next(1, 3);
                }

                
            }

            tracking.ListTaskWorked = result;
            dataService.dbWorker.WriteTrackingTaskDS(tracking);
        }
        private List<Task> createGhostTask(List<Task> ghost, int numOfTask, int i , int j)
        {
            Random r = new Random();
            List<Task> result = new List<Task>();
            for(int k = 0; k < numOfTask; k++)
            {
                Task t = new Task("task code: " + Convert.ToString(k) + Convert.ToString(i) + "-" + Convert.ToString(j) + "-" + numOfTask, j % 10, 120);
                Boolean chay = true;
                while (chay)
                {
                    chay = false;
                    t.TaskCode = DateTime.Now.GetHashCode() + 1 + k + r.Next(2, 300000);
                    for (int pp = 0; pp < ghost.Count; pp++)
                    {
                        if (t.TaskCode == ghost[pp].TaskCode)
                        {
                            chay = true;
                        }
                    }
                }
                t.RemainTime = r.Next(30, 600);
                result.Add(t);
            }

            return result;
        }
        private List<TaskWorked> createListGhostTW(List<Task> tl, DateTime ts)
        {
            List<TaskWorked> result = new List<TaskWorked>();
            Random r = new Random();
            for (int i = 0; i < tl.Count; i++)
            {
                TaskWorked tw = new TaskWorked();
                tw.AdditionalWork = r.Next(0, 300);
                tw.RemainingTime = tl[i].RemainTime - r.Next(-50, 120);
                if (tw.RemainingTime < 0)
                {
                    tw.RemainingTime = 0;
                }
                tl[i].RemainTime = tw.RemainingTime;
                tw.TaskCode = tl[i].TaskCode;
                tw.TaskName = tl[i].Name;
                tw.TimeStamp = ts;
                result.Add(tw);
            }


            return result;
        }
        #endregion

        public DataTable loadTaskReport()
        {
            try
            {
                return dataService.dbWorker.readScheduleReport().TaskReport;
                //ScheduleReport report = new ScheduleReport();
                //RWReportData.readScheduleReport(ref report);
                //return report.TaskReport;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return null;
            }
        }

        public DataTable loadSummaryReport()
        {
            try
            {
                return dataService.dbWorker.readScheduleReport().SummaryReport;
                //ScheduleReport report = new ScheduleReport();
                //RWReportData.readScheduleReport(ref report);
                //return report.SummaryReport;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return null;
            }
        }

        public List<JskeEvent> getListJskeEvent(DateTime from, DateTime to)
        {
            List<JskeEvent> result = new List<JskeEvent>();

            List<JskeEvent> listEventFromDiary = new List<JskeEvent>();
            List<JskeEvent> listEventFromAlgo = new List<JskeEvent>();

            //Load dữ liệu vào ListDiary và ListSchedule trong Engine
            diary.loadEvents(ref listEventFromDiary, ref listEventFromAlgo, scheduleList.ListSchedJskeEvt, from, to);
            //merge 2 list lại và sắp xếp theo thứ tự thời gian giảm dần về quá khứ
            for (int i = 0; i < listEventFromDiary.Count; i++)
            {
                result.Add(listEventFromDiary[i]);
            }
            for (int i = 0; i < listEventFromAlgo.Count; i++)
            {
                result.Add(listEventFromAlgo[i]);
            }
            //xep lai list result
            result.Sort(delegate(JskeEvent ev1, JskeEvent ev2)
            {
                return ev2.EventStart.CompareTo(ev1.EventStart);
            });

            for (int i = 0; i < result.Count; i++)
            {
                if (result[i].TaskName == null)
                    result[i].TaskName = "";
                if (result[i].ProjectName == null)
                    result[i].ProjectName = "";
                if (result[i].WorkingHourName == null)
                    result[i].WorkingHourName = "";
            }
            return result;
        }

        public List<JskeEvent> getListJskeEventInDiary(DateTime from, DateTime to)
        {
            return diary.loadEventInDiary(from, to);
        }

        public AnalysisDS createAnalysis(DateTime _from, DateTime _to)
        {
            diary.Analysis = new AnalysisDS();
            diary.analyze(_from, _to);
            return diary.Analysis;
        }

        public AnalysisDS createAnalysis(List<JskeEvent> listJskeEvent)
        {
            Double TotalTime = 0.0;
            for (int i = 0; i < listJskeEvent.Count; i++)
            {
                TotalTime += (Double)listJskeEvent[i].EventDuration;
            }
            diary.Analysis = new AnalysisDS();
            diary.analyze(listJskeEvent, TotalTime);
            return diary.Analysis;
        }

        public void saveListResult(List<JskeEvent> jskeEvents, List<int> listDeletedEventID, List<int> listNewEvent, EventType evt)
        {
            #region xoa Event (jskeEvents không chứa những event thuộc list này)
            // Chỉnh list eventSchedule: Những event đã bị xóa: co trong schedule cũ nhưng ko có trong result
            // Chỉnh list diaryEvent: Những event đã bị xóa: có trong diary cũ nhưng ko có trong result
            Boolean isInListDiary = false;
            for (int i = 0; i < listDeletedEventID.Count; i++)
            {
                isInListDiary = false;
                for (int j = 0; j < diary.ListEventInDiary.Count; j++)
                {
                    if (diary.ListEventInDiary[j].EventID == listDeletedEventID[i])
                    {
                        diary.ListEventInDiary.Remove(diary.ListEventInDiary[j]);
                        isInListDiary = true;
                        break;
                    }
                }
                if (!isInListDiary)
                {
                    for (int j = 0; j < scheduleList.ListSchedJskeEvt.Count; j++)
                    {
                        if (scheduleList.ListSchedJskeEvt[j].EventID == listDeletedEventID[i])
                        {
                            scheduleList.ListSchedJskeEvt.Remove(scheduleList.ListSchedJskeEvt[j]);
                            break;
                        }
                    }
                }
            }
            #endregion

            #region Them Event mới (jskeEvents có chứa những event thuộc list này)
            //Cập nhật lại danh sách Event mới vao Diary
            for (int i = 0; i < listNewEvent.Count; i++)
            {
                for (int j = 0; j < jskeEvents.Count; j++)
                {
                    if (listNewEvent[i] == jskeEvents[j].EventID)
                    {
                        diary.ListEventInDiary.Add(jskeEvents[j]);
                        //xóa khỏi jskeEvents
                        jskeEvents.RemoveAt(j);
                        j--;
                    }
                }
            }
            #endregion

            #region Đồng bộ dữ liệu ListDiay và ScheduleList
            //sau khi remove những event mới, xóa những evt đáng xóa, bây giờ những evt nào thuộc jskeEvt và ScheduleList phải được move sang Diary
            int removePos = -1;
            for (int i = 0; i < jskeEvents.Count; i++)
            {
                removePos = -1;
                for (int j = 0; j < scheduleList.ListSchedJskeEvt.Count; j++)
                {
                    //thuc hien thao tac move
                    if (jskeEvents[i].EventID == scheduleList.ListSchedJskeEvt[j].EventID)
                    {
                        //them vao Diary
                        diary.ListEventInDiary.Add(jskeEvents[i]);
                        //xoa trong jskeEvent va ScheduleList

                        if (removePos == -1)
                        {
                            removePos = i;
                        }
                        scheduleList.ListSchedJskeEvt.RemoveAt(j);
                        j--;
                    }
                }
                if (removePos > -1)
                {
                    jskeEvents.RemoveAt(i);
                    i--;
                }
            }
            #endregion
            diary.TheEventType = evt;
            //Save the result
            saveDiaryDataToBinaryFile();
        }

        public void loadDiaryDataToEngine()
        {
            this.diary = dataService.dbWorker.ReadDiaryDS();
            diary.TheEventType.Add("Email");
            diary.TheEventType.Add("Wait");
            diary.TheEventType.Add("Break");
            diary.TheEventType.Add("Eat");
            diary.TheEventType.Add("Bath");
            diary.TheEventType.Add("Sleep");
            diary.TheEventType.Add("Meeting");
            diary.TheEventType.Add("Telephone");
            diary.TheEventType.Add("Internet");
            diary.TheEventType.Add("Move");
            diary.TheEventType.Add("Paper & Document");
            diary.TheEventType.Add("Prepare");
            diary.TheEventType.Add("Planning");
            diary.TheEventType.Add("Leave");
            diary.TheEventType.Add("Gossip");
            diary.TheEventType.Add("Others");

            this.scheduleList = dataService.dbWorker.ReadListEvent();
        }

        public void saveDiaryDataToBinaryFile()
        {
            dataService.dbWorker.WriteDiaryDS(diary);
            dataService.dbWorker.WriteListEvent(scheduleList);
        }

        public EventType loadEventTypeData()
        {
            if (diary == null || diary.TheEventType.TypeName == null)
            {
                return null;
            }
            else
            {
                return diary.TheEventType;
            }
        }


        public List<JskeSerie> getBurndownData(DateTime from, DateTime to)
        {
            List<JskeSerie> result = new List<JskeSerie>();
            List<TaskBurndown> burndown = createTaskBurndownData(from, to);
            List<Double> seriesCode = new List<Double>();
            if (burndown.Count > 0)
            {
                //xây dựng cây Root
                JskeSerie root = new JskeSerie("Total");
                root.taskCode = -1;
                seriesCode.Add(root.taskCode);
                result.Add(root);
                for (int i = 0; i < burndown.Count; i++)
                {
                    root.allPoints.Add(new JskePoint(burndown[i].TheDay.DayOfYear, burndown[i].TotalRemainTime));
                    
                    //Xây dựng các cây burndown khác
                    for (int j = 0; j < burndown[i].ListBDTaskDetail.Count; j++)
                    {
                        //một là nó có sẵn, hai là nó chưa có. nếu chưa có thì tạo thêm, nếu có rồi thì add vô
                        if (seriesCode.Contains(burndown[i].ListBDTaskDetail[j].TaskID))
                        {
                            //có sẵn, chỉ việc thêm point vào là được
                            for (int k = 0; k < seriesCode.Count; k++)
                            {
                                //tìm kiếm
                                if (burndown[i].ListBDTaskDetail[j].TaskID == seriesCode[k])
                                {
                                    result[k].allPoints.Add(new JskePoint(burndown[i].TheDay.DayOfYear, burndown[i].ListBDTaskDetail[j].RemainTime));
                                    break;
                                }
                            }
                        }
                        else
                        {
                            JskeSerie child = new JskeSerie(burndown[i].ListBDTaskDetail[j].TaskName);
                            child.allPoints.Add(new JskePoint(burndown[i].TheDay.DayOfYear, burndown[i].ListBDTaskDetail[j].RemainTime));
                            child.taskCode = burndown[i].ListBDTaskDetail[j].TaskID;
                            seriesCode.Add(child.taskCode);
                            result.Add(child);
                        }
                    }
                }
                
            }

            return result;
        }

        public List<PiechartItem> getPiechartData()
        {
            List<PiechartItem> result = new List<PiechartItem>();
            List<Task> currTskl = taskList.GetTaskList;
            for (int i = 0; i < taskList.GetTaskList.Count; i++)
            {                
                result.Add(new PiechartItem(currTskl[i].RemainTime, currTskl[i].Name));
            }

            result.Sort(delegate(PiechartItem p1, PiechartItem p2)
            {
                return p1.yVal.CompareTo(p2.yVal);
            });
            return result;
        }

        public List<PiechartItem> getTaskPriorityData()
        {
            List<PiechartItem> result = new List<PiechartItem>();
            List<Task> currTskl = taskList.GetTaskList;
            for (int i = 0; i < taskList.GetTaskList.Count; i++)
            {
                result.Add(new PiechartItem(currTskl[i].RemainTime, Convert.ToString(currTskl[i].Priority)));
            }

            result.Sort(delegate(PiechartItem p1, PiechartItem p2)
            {
                return p1.xVal.CompareTo(p2.xVal);
            });

            for (int i = 0; i < result.Count - 1; i++)
            {
                if (result[i].xVal.Equals(result[i + 1].xVal))
                {
                    result[i].yVal += result[i + 1].yVal;
                    result.RemoveAt(i + 1);
                    i--;
                }
            }
            result.Sort(delegate(PiechartItem p1, PiechartItem p2)
            {
                return p1.yVal.CompareTo(p2.yVal);
            });
            
            return result;
        }

        public void loadTrackingTaskData()
        {
            taskList = dataService.dbWorker.readTaskList();
            //RWTaskList.readTaskList(ref taskList);
            //this.trackingTask = RWDiaryAndTracking.ReadTrackingTaskDS();
            this.trackingTask = dataService.dbWorker.ReadTrackingTaskDS();
        }
        public void saveTrackingTaskData()
        {
            dataService.dbWorker.WriteTrackingTaskDS(this.trackingTask);
        }

        public void saveListTaskWorked(List<TaskWorked> listTW)
        {
            listTW.Sort(delegate(TaskWorked t1, TaskWorked t2)
            {
                return t1.TimeStamp.CompareTo(t2.TimeStamp);
            });

            if (listTW.Count > 0)
            {
                #region cập nhật remainingTime cho Tasklist
                if (listTW.Last().TimeStamp.Date == DateTime.Now.Date)
                {
                    TaskList taskList = new TaskList();
                    taskList = dataService.dbWorker.readTaskList();
                    //RWTaskList.readTaskList(ref taskList);
                    for (int i = listTW.Count - 1; i >= 0; i--)
                    {
                        if (listTW[i].TimeStamp.Date < DateTime.Now.Date)
                        {
                            break;//da cap nhat xong
                        }
                        else if (listTW[i].TimeStamp.Date == DateTime.Now.Date)
                        {
                            for (int j = 0; j < taskList.GetTaskList.Count; j++)
                            {
                                if (listTW[i].TaskCode == taskList.GetTaskList[j].TaskCode)
                                {
                                    taskList.GetTaskList[j].RemainTime = listTW[i].RemainingTime;
                                    break;
                                }
                            }
                        }
                    }
                    dataService.dbWorker.writeTaskList(taskList);
                }
                #endregion
            }

            this.trackingTask.addTaskWorkedToList(listTW);
            saveTrackingTaskData();

            
        }

        public List<TaskBurndown> createTaskBurndownData(DateTime from, DateTime to)
        {
            this.trackingTask.buildBurndownData(from.Date, to.Date);
            return this.trackingTask.BurndownGraphDataFromTo;
        }

        public List<TaskWorked> getTaskWorkFromTo(DateTime from, DateTime to)
        {
            List<TaskWorked> result = new List<TaskWorked>();
            result = this.trackingTask.getListTWFromTo(from.Date, to.Date);
            if (result.Count > 0)
            {
                if (to.Date >= DateTime.Now.Date && result.Last().TimeStamp >= DateTime.Now.Date)
                {
                    //cập nhật danh sách result và đưa vào những event mới của taskList
                    int pivot = result.Count - 1;
                    int count = 0;
                    for (int i = result.Count - 1; i >= 0; i--)
                    {
                        if (result[i].TimeStamp == DateTime.Now.Date)
                        {
                            pivot = i;
                            count = count + 1;
                        }
                        else
                        {
                            break;
                        }
                    }
                    //result.RemoveRange(pivot, count);
                    for (int i = 0; i < taskList.GetTaskList.Count; i++)
                    {
                        Boolean isNewTW = true;
                        for (int j = pivot; j < result.Count; j++)
                        {
                            if (taskList.GetTaskList[i].TaskCode == result[j].TaskCode)
                            {
                                isNewTW = false;
                                break;
                            }
                        }
                        if (isNewTW)
                        {
                            TaskWorked tw = new TaskWorked();
                            tw.TaskCode = taskList.GetTaskList[i].TaskCode;
                            tw.Notes = "Write notes for Task: " + taskList.GetTaskList[i].Name;
                            tw.RemainingTime = taskList.GetTaskList[i].RemainTime;
                            tw.TaskName = taskList.GetTaskList[i].Name;
                            tw.TimeStamp = DateTime.Now.Date;
                            tw.AdditionalWork = 0;
                            result.Add(tw);
                        }
                    }
                }
            }
            if (result.Count == 0 && to.Date >= DateTime.Now.Date)// Trường hợp đặc biệt
            {
                List<TaskWorked> current = getCurrentTaskWorked();
                result.AddRange(current);
            }
            return result;
        }

        private List<TaskWorked> getCurrentTaskWorked()
        {
            List<TaskWorked> result = new List<TaskWorked>();
            TaskList taskList = new TaskList();

            taskList = dataService.dbWorker.readTaskList();
            for (int i = 0; i < taskList.GetTaskList.Count; i++)
            {
                TaskWorked tw = new TaskWorked();
                tw.TaskCode = taskList.GetTaskList[i].TaskCode;
                tw.Notes = "Write notes for Task: " + taskList.GetTaskList[i].Name;
                tw.RemainingTime = taskList.GetTaskList[i].RemainTime;
                tw.TaskName = taskList.GetTaskList[i].Name;
                tw.TimeStamp = DateTime.Now.Date;
                tw.AdditionalWork = 0;

                result.Add(tw);
            }


            return result;
        }

        private Boolean isTaskWorkedCompatibleTaskList(TaskWorked tw, TaskList taskList)
        {
            Boolean result = false;
            for (int i = 0; i < taskList.GetTaskList.Count; i++)
            {
                if (tw.TaskCode == taskList.GetTaskList[i].TaskCode)
                {
                    result = true;
                    return result;
                }
            }
            return result;
        }

        #endregion


        #endregion


        public List<JskeEvent> getScheduleCalendar()
        {
            return dataService.dbWorker.ReadListSchedEvent().ListSchedJskeEvt;
        }
    }
}
